package com.uzai.console.component;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ResourceUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.HashMap;

/**
 * 获取IP地址工具类
 * @author jianghan
 * @date 2017/1/10
 */
@Component
public class IpInfoUtil {

    @Autowired
    private RestTemplate restTemplate;

    public class IpInfo{
        private String ip;         //IP地址
        private String country;    //IP所在国家
        private String province;   //IP所在省
        private String city;       //IP所在市

        public String getIp() {
            return ip;
        }

        public void setIp(String ip) {
            this.ip = ip;
        }

        public String getCountry() {
            return country;
        }

        public void setCountry(String country) {
            this.country = country;
        }

        public String getProvince() {
            return province;
        }

        public void setProvince(String province) {
            this.province = province;
        }

        public String getCity() {
            return city;
        }

        public void setCity(String city) {
            this.city = city;
        }
    }


    /**
     * 获取请求用户的本地IP地址信息
     * @return
     */
    public IpInfo getRequestIpInfo() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        return getRequestIpInfo(request);
    }

    /**
     * 获取请求用户的外网IP地址信息
     * @return
     */
    public String getInterIP2(){
        String localip = null;// 本地IP，如果没有配置外网IP则返回它
        String netip = null;// 外网IP
        Enumeration<NetworkInterface> netInterfaces;
        try {
            netInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip = null;
            boolean finded = false;// 是否找到外网IP
            while (netInterfaces.hasMoreElements() && !finded) {
                NetworkInterface ni = netInterfaces.nextElement();
                Enumeration<InetAddress> address = ni.getInetAddresses();
                while (address.hasMoreElements()) {
                    ip = address.nextElement();
                    if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 外网IP
                        netip = ip.getHostAddress();
                        finded = true;
                        break;
                    } else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 内网IP
                        localip = ip.getHostAddress();
                    }
                }
            }
            if (netip != null && !"".equals(netip)) {
                return netip;
            } else {
                return localip;
            }
        } catch (SocketException e) {
        }

        return localip;
    }


    /**
     * 获取请求用户的IP地址信息对象
     * @param request
     * @return
     */
    private IpInfo getRequestIpInfo(HttpServletRequest request) {

        IpInfo inInfo = new IpInfo();

        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        if ("0:0:0:0:0:0:0:1".equals(ip)){
            ip = getLocalhostIp();
            inInfo.setIp(ip);
            //局域网，ip传递为""
            getRegion("", inInfo);
        }if ("127.0.0.1".equals(ip)){
            ip = getLocalhostIp();
            inInfo.setIp(ip);
            //局域网，ip传递为""
            getRegion("", inInfo);
        }else{
            inInfo.setIp(ip);
            getRegion(ip, inInfo);
        }
        return inInfo;
    }

    private String getLocalhostIp(){
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
        }
        return null;
    }

    private IpInfo getRegion(String ip, IpInfo inInfo){
        try{
            String url = "https://ip.taobao.com/outGetIpInfo";
            MultiValueMap<String, String> param = new LinkedMultiValueMap<>();
            param.add("ip", ip);
            param.add("accessKey", "alibaba-inc");
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(param, headers);
            ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
            if(response.getStatusCode() == HttpStatus.OK){
                //远程调用失败，获取msg异常信息，根据自己的业务进行合理处理
                JSONObject data = response.getBody().getJSONObject("data");
                if(data != null){
                    //国家
                    String country = data.getString("country");
                    inInfo.setCountry(country);
                    //省
                    String region = data.getString("region");
                    inInfo.setProvince(region);
                    //市
                    String city = data.getString("city");
                    inInfo.setCity(city);
                }
            }
        }catch (Exception e){
        }
        return inInfo;
    }

    /**
     * 通过ip2region.xdb本地库来查询IP归属
     * @author lucher
     * @date 2022/11/25 11:40
     * @param ip
     * @return java.lang.String
     */
    public String getIpAddress(String ip){
        String region = null;
        if ("127.0.0.1".equals(ip) || ip.startsWith("192.168")) {
            return "局域网 ip";
        }
        try {
            File file = ResourceUtils.getFile("classpath:ipdb/ip2region.xdb");
            String dbPath = file.getPath();
            Searcher searcher = Searcher.newWithFileOnly(dbPath);
            region = searcher.search(ip);

        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        } catch (Exception e){
        }
        return region;
    }


}
